package com.atguigu.gulimall.cart.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.cart.feign.ProductFeignService;
import com.atguigu.gulimall.cart.interceptor.CartInterceptor;
import com.atguigu.gulimall.cart.vo.Cart;
import com.atguigu.gulimall.cart.vo.CartItem;
import com.atguigu.gulimall.cart.vo.SkuInfoVo;
import com.atguigu.gulimall.cart.vo.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CartServiceImpl implements CartService{

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private ThreadPoolExecutor executor;

    private static String CART_PREFIX = "gulimall:cart:";

    @Override
    public List<CartItem> getCheckItem() throws ExecutionException, InterruptedException {
        Cart cart = getCart();
        List<CartItem> items = cart.getItems();
        List<CartItem> cartItems = items.stream()
                .map(item->{
                    //须查询最新的价格信息
                    //TODO 循环远程调用，性能太差，须改进
                    BigDecimal price = productFeignService.getPriceBySkuId(item.getSkuId());
                    item.setPrice(price);
                    return item;})
                .filter(item -> item.getCheck()).collect(Collectors.toList());

        return cartItems;
    }

    @Override
    public void countItem(Long skuId, int num) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String json = (String) cartOps.get("" + skuId);
        CartItem cartItem = JSON.parseObject(json, CartItem.class);
        cartItem.setCount(num);
        cartOps.put(""+skuId,JSON.toJSONString(cartItem));
    }

    @Override
    public void deleteItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        cartOps.delete(skuId+"");
    }

    @Override
    public void checkItem(Long skuId, boolean check) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String json = (String) cartOps.get("" + skuId);
        CartItem cartItem = JSON.parseObject(json, CartItem.class);
        cartItem.setCheck(check);
        cartOps.put(""+skuId,JSON.toJSONString(cartItem));
    }

    @Override
    public Cart getCart() throws ExecutionException, InterruptedException {
        UserInfoVo userInfoVo = CartInterceptor.toThreadLocal.get();
        if (userInfoVo.getUserId() == null){
            //没登录，返回临时购物车
            String userKey = userInfoVo.getUserKey();
            //获取临时购物车中的信息
            Cart tempCart = getCartByKey(userKey);
            return tempCart;
        }else{
            //登录了，返回用户购物车；注意，还需合并临时购物车
            Long userId = userInfoVo.getUserId();
            Cart cart = getCartByKey(userId+"");

            //如果cart为空，则新建一个cart
            if (cart == null){
                cart = new Cart();
            }

            String userKey = userInfoVo.getUserKey();
            //获取临时购物车中的信息
            Cart tempCart = getCartByKey(userKey);
            if (tempCart != null && tempCart.getItems().size() > 0){
                for (CartItem item : tempCart.getItems()) {
                    addCartItem(item.getSkuId(),item.getCount());
                }
                cart = getCartByKey(userId+"");
                clearCart(userKey);
            }

            return cart;
        }
    }

    private void clearCart(String key) {
        redisTemplate.delete(CART_PREFIX+key);
    }

    private Cart getCartByKey(String userKey) {
        BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(CART_PREFIX + userKey);
        List<Object> tempCartItems = hashOps.values();
        if (tempCartItems != null && tempCartItems.size() > 0){
            List<CartItem> cartItems = tempCartItems.stream().
                    map(item -> JSON.parseObject((String) item, CartItem.class)).
                    collect(Collectors.toList());
            Cart cart = new Cart();
            cart.setItems(cartItems);
            return cart;
        }
        return new Cart();
    }

    @Override
    public CartItem getCartItem(Long skuId) {

        String json = (String) getCartOps().get(skuId + "");
        CartItem cartItem = JSON.parseObject(json, CartItem.class);
        return cartItem;
    }

    @Override
    public CartItem addCartItem(Long skuId, int num) throws ExecutionException, InterruptedException {

        /**
         * TODO 多个用户同时添加可能会有并发问题
         * */

        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String s = (String) cartOps.get(skuId + "");
        CartItem cartItem1 = JSON.parseObject(s, CartItem.class);
        if (cartItem1 != null){
            //如果购物车中已经有了，只需要添加数量即可，也不用去查sku信息了
            cartItem1.setCount(cartItem1.getCount()+num);
            cartOps.put(skuId+"",JSON.toJSONString(cartItem1));
            return cartItem1;
        }

        //如果购物车中没有，则增加一个购物项，以下逻辑都是基于购物车中没有的情况

        CartItem cartItem = new CartItem();

        //先查询商品信息
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            R info = productFeignService.info(skuId);
            //这里不用判断状态码了，如果有错应该直接往外抛出错误
            SkuInfoVo skuInfo = info.getData(new TypeReference<SkuInfoVo>() {
            }, "skuInfo");
            cartItem.setCheck(true);
            cartItem.setCount(num);
            cartItem.setImage(skuInfo.getSkuDefaultImg());
            cartItem.setPrice(skuInfo.getPrice());
            cartItem.setSkuId(skuId);
            cartItem.setTitle(skuInfo.getSkuTitle());
        }, executor);


        //查询商品销售信息
        CompletableFuture<Void> voidCompletableFuture2 = CompletableFuture.runAsync(() -> {
            List<String> attrNameAndValues = productFeignService.getAttrValueStringBySkuId(skuId);
            cartItem.setSkuAttrValues(attrNameAndValues);
        }, executor);

        CompletableFuture.allOf(voidCompletableFuture,voidCompletableFuture2).get();

        cartOps.put(skuId+"", JSON.toJSONString(cartItem));
        return cartItem;
    }

    private BoundHashOperations<String, Object, Object> getCartOps(){
        UserInfoVo userInfoVo = CartInterceptor.toThreadLocal.get();
        //redisTemplate.opsForHash() 也可以用这个方法，但是每次都要输入最前面的key，麻烦
        BoundHashOperations<String, Object, Object> boundHashOperations = null;
        if (userInfoVo.getUserId() == null){
            //如果没登录，返回临时购物车
            boundHashOperations
                    = redisTemplate.boundHashOps(CART_PREFIX+userInfoVo.getUserKey());
        }else{
            //如果登录了，返回用户购物车
            boundHashOperations
                    = redisTemplate.boundHashOps(CART_PREFIX+userInfoVo.getUserId());
        }
        return boundHashOperations;
    }
}
